#include "systemc.h"

class PointStruct {
public:
  // 默认构造函数
  PointStruct() : x_crd(0), y_crd(0), z_crd(0) {
    for (int i = 0; i < 6; ++i) {
      feature[i] = 0;
    }
  }

  // 带参数的构造函数
  PointStruct(sc_dt::sc_uint<16> x, sc_dt::sc_uint<16> y, sc_dt::sc_uint<8> z) 
      : x_crd(x), y_crd(y), z_crd(z) {
    for (int i = 0; i < 6; ++i) {
      feature[i] = 0;
    }
  }

  // Setter 和打印函数
  void setFeature(int idx, sc_dt::sc_uint<16> value) {
    if (idx >= 0 && idx < 6) feature[idx] = value;
    else throw std::out_of_range("Index out of range");
  }

  void print() const {
    std::cout << *this << std::endl;
  }

  // 重载 << 运算符
  friend std::ostream& operator<<(std::ostream& os, const PointStruct& point) {
    os << "Point coordinates: ("
       << point.x_crd.to_uint() << ", "
       << point.y_crd.to_uint() << ", "
       << point.z_crd.to_uint() << "), Features: [";
    for (int i = 0; i < 6; ++i) {
      os << point.feature[i].to_uint();
      if (i < 5) os << ", ";
    }
    os << "]";
    return os;
  }

private:
  sc_dt::sc_uint<16> feature[6];
  sc_dt::sc_uint<8>  z_crd;
  sc_dt::sc_uint<16> y_crd;
  sc_dt::sc_uint<16> x_crd;
};

// Producer 模块
SC_MODULE(Producer) {
  sc_core::sc_port<sc_core::sc_fifo_out_if<PointStruct> > out;

  SC_CTOR(Producer) {
    SC_THREAD(produce);
  }

  void produce() {
    for (int i = 0; i < 10; ++i) {
      PointStruct point(i, i * 2, i * 3);
      for (int j = 0; j < 6; ++j) {
        point.setFeature(j, i * 10 + j);
      }
      std::cout << "Producer: Sending PointStruct " << i << std::endl;
      out->write(point);
    }
  }
};

// Consumer 模块
SC_MODULE(Consumer) {
  sc_core::sc_port<sc_core::sc_fifo_in_if<PointStruct> > in;

  SC_CTOR(Consumer) {
    SC_THREAD(consume);
  }

  void consume() {
    for (int i = 0; i < 10; ++i) {
      PointStruct point;
      in->read(point);
      std::cout << "Consumer: Received PointStruct " << i << std::endl;
      point.print();
      wait(15, sc_core::SC_NS);
    }
  }
};

// 主函数
int sc_main(int argc, char* argv[]) {
  sc_core::sc_fifo<PointStruct> fifo; // FIFO 缓冲区

  Producer producer("Producer");
  Consumer consumer("Consumer");

  // 连接模块
  producer.out(fifo);
  consumer.in(fifo);

  // 启动仿真
  sc_core::sc_start();

  return 0;
}
